package com.chenfan.process.event.callback;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chenfan.ccp.common.result.R;
import com.chenfan.ccp.entity.BaseUserVO;
import com.chenfan.ccp.util.tool.JsonUtil;
import com.chenfan.infra.constants.CommonBeanConstants;
import com.chenfan.infra.context.UserContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Objects;

/**
 * @author liuming
 * @date 2021/11/1
 */
@Slf4j
@Component
public class ThirdCallback {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 根据url获取结果
     *
     * @param serviceName
     * @param uri
     * @param param
     * @return
     */
    @Retryable(value = {Exception.class},maxAttempts = 3,backoff = @Backoff(delay = 2000L,multiplier = 3))
    public String getResponseByUrl(String serviceName, String uri, Object param, String headToken) throws UnsupportedEncodingException {
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
        log.info("approvalCallBack:{}", JSONObject.toJSONString(param));
        if (CollectionUtils.isEmpty(instances)) {
            logger.warn("实例={}暂未寻找到可用的服务列表", serviceName);
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        BaseUserVO baseUserVO = JSONObject.parseObject(JSONObject.toJSONString(UserContextHolder.getUserVo()), BaseUserVO.class);
        log.info("BASE_USERVO=============={}",baseUserVO);
        if (!StringUtils.isEmpty(headToken)) {
            headers.add("Authorization", headToken);
            headers.add("currentUser",  JSON.toJSONString(baseUserVO));
            if (Objects.nonNull(baseUserVO.getTenantId())) {
                headers.add(CommonBeanConstants.TENANT_ID, baseUserVO.getTenantId().toString());
            }
        }
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        String content = (param instanceof String ? param.toString() : JsonUtil.obj2String(param));
        HttpEntity<String> request = new HttpEntity<>(content, headers);

        ServiceInstance serviceInstance = instances.stream().findAny().get();
        String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/" + uri;
        String post = postInfo(serviceName, headers, content, request, url);
        return post;
    }

    /**
     * Retryable 注解必须要是public方法
     */

    public String postInfo(String serviceName, HttpHeaders headers, String content, HttpEntity<String> request, String url) {
        // 调用接口之前先把数据落地到数据库
        String post = restTemplate.postForObject(url, request, String.class);
        logger.info("调用服务:{}, 调用接口:{}, 调用参数:{}, 请求头:{}", serviceName, url, content, headers);
        logger.info("回调调用接口成功:{}", post);
        //如果为空 说明结果正常
//        if(Objects.isNull(post)){
//            log.error("回调业务异常");
//            throw new RuntimeException("回调业务异常");
//        }
        if(Objects.nonNull(post) ){
            R result = JsonUtil.string2Obj(post , R.class);
            // 返回码不为空 并且
            if(!(result.getCode() == 0 || result.getCode() == 200)){
                throw new RuntimeException("回调业务异常");
            }
        }
        return post;
    }

    @Recover
    public String recover(Exception e){
        logger.error("执行三次回调失败");
        //记日志到数据库 或者调用其余的方法
        return "";
    }
//    /**
//     * 创建指定字符集的RestTemplate
//     *
//     * @param charset 编码
//     * @return 返回结果
//     */
//    public static RestTemplate getInstance(String charset) {
//        RestTemplate restTemplate = new RestTemplate();
//        restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName(charset)));
//        return restTemplate;
//    }
}
